{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [],
   "source": [
    "import boolean as boolean\n",
    "\n",
    "import numpy as np\n",
    "import sqlite3 as sqlite3\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    " \n",
    "#引入matplotlib库\n",
    "\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "\n",
    "from matplotlib import cm\n",
    "from matplotlib.ticker import LinearLocator, FormatStrFormatter\n",
    "\n",
    "\n",
    "from pylab import *\n",
    "\n",
    "class booleannet:\n",
    "    def __init__(self, dbname, ci ,ch, co):\n",
    "        \n",
    "        #self.con = sqlite3.connect(dbname)\n",
    "        self.inode=((np.random.rand(1,ci))>0)[0].tolist()\n",
    "        self.hnode=((np.random.rand(1,ch))>0)[0].tolist()\n",
    "        self.onode=((np.random.rand(1,co))>0)[0].tolist()\n",
    "        self.wi=((np.random.rand(ch,ci))>0.5)\n",
    "        self.wo=((np.random.rand(co,ch))>0.5)\n",
    "    def feedforward(self):\n",
    "        self.hnode=boolean.otimes_bv_bm(self.inode,self.wi)\n",
    "        self.onode=boolean.otimes_bv_bm(self.hnode,self.wo)\n",
    "    def backPropagate(self, targets):        \n",
    "        #calculate error\n",
    "        self.error=boolean.qtimes_bv_bv(targets,self.onode)\n",
    "        #self.wo=boolean.otimes_bv_bm(error,self.wo)\n",
    "        #self.hnodetargets=boolean.otimes_bv_bm(self.error, np.transpose(self.wo))\n",
    "        #self.hnode_error=[boolean.otimes_b_b(x,y) for x,y in zip(self.hnodetargets,self.hnode)]\n",
    "        #modify out weight matrix\n",
    "        self.wo=(boolean.qtimes_bv_bm(self.error,self.wo.transpose())).transpose()\n",
    "        #calculate hnode error\n",
    "        self.hnodetargets=boolean.otimes_bv_bm(targets,self.wo.transpose())\n",
    "        self.hnode_error=boolean.qtimes_bv_bv(self.hnodetargets,self.hnode)\n",
    "        self.hnode=self.hnodetargets\n",
    "        #modify input weight matrix\n",
    "        self.wi=(boolean.qtimes_bv_bm(self.hnode_error,self.wi.transpose())).transpose()\n",
    "        self.inode=boolean.otimes_bv_bm(self.hnode,self.wi.transpose())\n",
    "    def train(self,inputs,targets):\n",
    "        self.inode=inputs\n",
    "        self.feedforward()\n",
    "        self.backPropagate(targets)\n",
    "        \n",
    "\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_set(vin,von,n):\n",
    "    temp=[]\n",
    "    for i in range(n):\n",
    "        x=boolean.rand_bv(vin)\n",
    "        y=boolean.rand_bv(von)\n",
    "        temp.append([x,y])\n",
    "    return temp\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [],
   "source": [
    "op=imread('op.jpg')\n",
    "eq=imread('eq.jpg')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [],
   "source": [
    "bl1=booleannet('bl.db',9,8,4)\n",
    "\n",
    "nnset=test_set(9,4,96)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [],
   "source": [
    "#train\n",
    "for i in nnset:\n",
    "    for j in range(5):\n",
    "        bl1.train(i[0],i[1])\n",
    "        bl1.feedforward()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#test\n",
    "right=0\n",
    "for i in nnset:\n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    if bl1.onode==i[1]:\n",
    "        right+=1\n",
    "right\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "metadata": {},
   "outputs": [],
   "source": [
    "#train for net with 2 hidenode\n",
    "bl1=booleannet('bl.db',16,16,8)\n",
    "bl2=booleannet('bl.db',8,4,4)\n",
    "nnset=test_set(16,4,96)\n",
    "for i in nnset: \n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    #backPropagate\n",
    "    bl2.backPropagate(i[1])\n",
    "    bl1.backPropagate(bl2.inode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 152,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#test\n",
    "right=0\n",
    "for i in nnset:\n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    if bl2.onode==i[1]:\n",
    "        right+=1\n",
    "right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {},
   "outputs": [],
   "source": [
    "#train for net with 3 hidenode\n",
    "bl1=booleannet('bl.db',16,8,8)\n",
    "bl2=booleannet('bl.db',8,8,4)\n",
    "bl3=booleannet('bl.db',4,4,4)\n",
    "nnset=test_set(16,4,96)\n",
    "\n",
    "for i in nnset: \n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    bl3.inode=bl1.onode\n",
    "    bl3.feedforward()\n",
    "    #backPropagate\n",
    "    bl3.backPropagate(i[1])\n",
    "    bl2.backPropagate(bl3.inode)\n",
    "\n",
    "    bl1.backPropagate(bl2.inode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 156,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#test\n",
    "right=0\n",
    "for i in nnset:\n",
    "    bl1.inode=i[0]\n",
    "    bl1.feedforward()\n",
    "    bl2.inode=bl1.onode\n",
    "    bl2.feedforward()\n",
    "    bl3.inode=bl2.onode\n",
    "    bl3.feedforward()    \n",
    "    if bl3.onode==i[1]:\n",
    "        right+=1\n",
    "right"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig,axs=plt.subplots(nrows=1, ncols=5, figsize=(12, 6))\n",
    "axs[0].imshow(np.array([bl1.inode]),vmin=0,vmax=1)\n",
    "axs[0].set_title('inode')\n",
    "axs[0].set_axis_off()\n",
    "axs[1].imshow(bl1.wi,vmin=0,vmax=1)\n",
    "axs[1].set_title('wi')\n",
    "axs[1].set_axis_off()\n",
    "axs[2].imshow(np.array([bl1.hnode]),vmin=0,vmax=1)\n",
    "axs[2].set_title('hnode')\n",
    "axs[2].set_axis_off()\n",
    "axs[3].imshow(bl1.wo,vmin=0,vmax=1)\n",
    "axs[3].set_title('wo')\n",
    "axs[3].set_axis_off()\n",
    "axs[4].imshow(np.array([bl1.onode]),vmin=0,vmax=1)\n",
    "axs[4].set_title('onode')\n",
    "axs[4].set_axis_off()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#随机矩阵与矩阵相乘\n",
    "\n",
    "#准备所乘矩阵\n",
    "a=np.random.rand(12,12)\n",
    "x=a>0.5\n",
    "op=imread('op.jpg')\n",
    "eq=imread('eq.jpg')\n",
    "\n",
    "for i in range(0,6):\n",
    "    #准备随机矩阵\n",
    "    d=np.random.rand(12,12)\n",
    "\n",
    "    fig,axs=plt.subplots(nrows=1, ncols=6, figsize=(12, 6))\n",
    "\n",
    "\n",
    "\n",
    "    dd=d>0.5\n",
    "    #矩阵与矩阵相乘的结果为res1\n",
    "\n",
    "    res1=otimes_bm_bm(dd,x)\n",
    "    #矩阵与转置后的矩阵相乘的结果为res2\n",
    "\n",
    "    res2=otimes_bm_bm(dd,np.transpose(x))\n",
    "    #绘图表达\n",
    "    axs[0].imshow(dd,vmin=0,vmax=1)\n",
    "    axs[0].set_title('A')\n",
    "    axs[0].set_axis_off()\n",
    "\n",
    "    axs[1].imshow(op)\n",
    "    axs[1].set_axis_off()\n",
    "\n",
    "    axs[2].imshow(x,vmin=0,vmax=1)\n",
    "    axs[2].set_title('x')\n",
    "    axs[2].set_axis_off()\n",
    "\n",
    "    axs[3].imshow(eq)\n",
    "    axs[3].set_axis_off()\n",
    "\n",
    "    axs[4].imshow(res1,vmin=0,vmax=1)\n",
    "    axs[4].set_title('res1')\n",
    "    axs[4].set_axis_off()\n",
    "\n",
    "    axs[5].imshow(res2,vmin=0,vmax=1)\n",
    "    axs[5].set_title('res2')\n",
    "    axs[5].set_axis_off()\n",
    "\n",
    "\n",
    "    \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def __del__(self):\n",
    "        self.con.close()\n",
    "\n",
    "    def maketables(self):\n",
    "        self.con.execute('create table hiddennode(create_key)')\n",
    "        self.con.execute('create table wordhidden(fromid,toid,strength)')\n",
    "        self.con.execute('create table hiddenurl(fromid,toid,strength)')\n",
    "        self.con.commit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def getstrength(self, fromid, toid, layer):\n",
    "        if layer == 0:\n",
    "            table = 'wordhidden'\n",
    "        else:\n",
    "            table = 'hiddenurl'\n",
    "        res = self.con.execute('select strength from %s where fromid=%d and toid=%d' % (table, fromid, toid)).fetchone()\n",
    "        if res is None:\n",
    "            if layer == 0: return -0.2\n",
    "            if layer == 1: return 0\n",
    "        return res[0]\n",
    "\n",
    "    def setstrength(self, fromid, toid, layer, strength):\n",
    "        if layer == 0:\n",
    "            table = 'wordhidden'\n",
    "        else:\n",
    "            table = 'hiddenurl'\n",
    "        res = self.con.execute('select rowid from %s where fromid=%d and toid=%d' % (table, fromid, toid)).fetchone()\n",
    "        if res is None:\n",
    "            self.con.execute(\n",
    "                'insert into %s (fromid,toid,strength) values (%d,%d,%f)' % (table, fromid, toid, strength))\n",
    "        else:\n",
    "            rowid = res[0]\n",
    "            self.con.execute('update %s set strength=%f where rowid=%d' % (table, strength, rowid))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def generatehiddennode(self, wordids, urls):\n",
    "        if len(wordids) > 3: return None\n",
    "        # Check if we already created a node for this set of words\n",
    "        sorted_words = [str(id) for id in wordids]\n",
    "        sorted_words.sort()\n",
    "        createkey = '_'.join(sorted_words)\n",
    "        res = self.con.execute(\n",
    "            \"select rowid from hiddennode where create_key='%s'\" % createkey).fetchone()\n",
    "\n",
    "        # If not, create it\n",
    "        if res is None:\n",
    "            cur = self.con.execute(\n",
    "                \"insert into hiddennode (create_key) values ('%s')\" % createkey)\n",
    "            hiddenid = cur.lastrowid\n",
    "            # Put in some default weights\n",
    "            for wordid in wordids:\n",
    "                self.setstrength(wordid, hiddenid, 0, 1.0 / len(wordids))\n",
    "            for urlid in urls:\n",
    "                self.setstrength(hiddenid, urlid, 1, 0.1)\n",
    "            self.con.commit()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def getallhiddenids(self, wordids, urlids):\n",
    "        l1 = {}\n",
    "        for wordid in wordids:\n",
    "            cur = self.con.execute(\n",
    "                'select toid from wordhidden where fromid=%d' % wordid)\n",
    "            for row in cur: l1[row[0]] = 1\n",
    "        for urlid in urlids:\n",
    "            cur = self.con.execute(\n",
    "                'select fromid from hiddenurl where toid=%d' % urlid)\n",
    "            for row in cur: l1[row[0]] = 1\n",
    "        return list(l1.keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def setupnetwork(self, wordids, urlids):\n",
    "        # value lists\n",
    "        self.wordids = wordids\n",
    "        self.hiddenids = self.getallhiddenids(wordids, urlids)\n",
    "        self.urlids = urlids\n",
    "\n",
    "        # node outputs\n",
    "        self.ai = [1.0] * len(self.wordids)\n",
    "        self.ah = [1.0] * len(self.hiddenids)\n",
    "        self.ao = [1.0] * len(self.urlids)\n",
    "\n",
    "        # create weights matrix\n",
    "        self.wi = [[self.getstrength(wordid, hiddenid, 0)\n",
    "                    for hiddenid in self.hiddenids]\n",
    "                   for wordid in self.wordids]\n",
    "        self.wo = [[self.getstrength(hiddenid, urlid, 1)\n",
    "                    for urlid in self.urlids]\n",
    "                   for hiddenid in self.hiddenids]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def feedforward(self):\n",
    "        # the only inputs are the query words\n",
    "        for i in range(len(self.wordids)):\n",
    "            self.ai[i] = 1.0\n",
    "\n",
    "        # hidden activations\n",
    "        for j in range(len(self.hiddenids)):\n",
    "            tmpsum = 0.0\n",
    "            for i in range(len(self.wordids)):\n",
    "                tmpsum += self.ai[i] * self.wi[i][j]\n",
    "            self.ah[j] = tanh(tmpsum)\n",
    "\n",
    "        # output activations\n",
    "        for k in range(len(self.urlids)):\n",
    "            tmpsum = 0.0\n",
    "            for j in range(len(self.hiddenids)):\n",
    "                tmpsum += self.ah[j] * self.wo[j][k]\n",
    "            self.ao[k] = tanh(tmpsum)\n",
    "\n",
    "        return self.ao[:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def getresult(self, wordids, urlids):\n",
    "        self.setupnetwork(wordids, urlids)\n",
    "        return self.feedforward()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def backPropagate(self, targets, N=0.5):\n",
    "        # calculate errors for output\n",
    "        output_deltas = [0.0] * len(self.urlids)\n",
    "        for k in range(len(self.urlids)):\n",
    "            error = targets[k] - self.ao[k]\n",
    "            output_deltas[k] = dtanh(self.ao[k]) * error\n",
    "\n",
    "        # calculate errors for hidden layer\n",
    "        hidden_deltas = [0.0] * len(self.hiddenids)\n",
    "        for j in range(len(self.hiddenids)):\n",
    "            error = 0.0\n",
    "            for k in range(len(self.urlids)):\n",
    "                error += output_deltas[k] * self.wo[j][k]\n",
    "            hidden_deltas[j] = dtanh(self.ah[j]) * error\n",
    "\n",
    "        # update output weights\n",
    "        for j in range(len(self.hiddenids)):\n",
    "            for k in range(len(self.urlids)):\n",
    "                change = output_deltas[k] * self.ah[j]\n",
    "                self.wo[j][k] += N * change\n",
    "\n",
    "        # update input weights\n",
    "        for i in range(len(self.wordids)):\n",
    "            for j in range(len(self.hiddenids)):\n",
    "                change = hidden_deltas[j] * self.ai[i]\n",
    "                self.wi[i][j] += N * change"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def trainquery(self, wordids, urlids, selectedurl):\n",
    "        # generate a hidden node if necessary\n",
    "        self.generatehiddennode(wordids, urlids)\n",
    "\n",
    "        self.setupnetwork(wordids, urlids)\n",
    "        self.feedforward()\n",
    "        targets = [0.0] * len(urlids)\n",
    "        targets[urlids.index(selectedurl)] = 1.0\n",
    "        self.backPropagate(targets)\n",
    "        self.updatedatabase()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "    def updatedatabase(self):\n",
    "        # set them to database values\n",
    "        for i in range(len(self.wordids)):\n",
    "            for j in range(len(self.hiddenids)):\n",
    "                self.setstrength(self.wordids[i], self.hiddenids[j], 0, self.wi[i][j])\n",
    "        for j in range(len(self.hiddenids)):\n",
    "            for k in range(len(self.urlids)):\n",
    "                self.setstrength(self.hiddenids[j], self.urlids[k], 1, self.wo[j][k])\n",
    "        self.con.commit()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
